//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   Moments_Field.i.hh
 * \author Jeremy Roberts
 * \date   Jul 11, 2011
 * \brief  MomentsField inline member definitions.
 * \note   Copyright (C) 2011 Jeremy Roberts. 
 */
//---------------------------------------------------------------------------//
// $Rev:: 133                                           $:Rev of last commit
// $Author:: j.alyn.roberts@gmail.com                   $:Author of last commit
// $Date:: 2011-09-08 19:31:48 +0000 (Thu, 08 Sep 2011) $:Date of last commit
//---------------------------------------------------------------------------//


#ifndef MOMENTS_FIELD_I_HH_
#define MOMENTS_FIELD_I_HH_

namespace slabtran
{

// Constructor.
template<class Equations, class D>
Moments_Field<Equations, D>::Moments_Field(SP_mesh mesh,
                                           int legendre_order,
                                           double init_val)
  :   Cell_Field<double> (mesh,
                          Moments<D>::number_moments(legendre_order)*
                          Equations::number_unknowns(),
                          init_val)
    , d_legendre_order(legendre_order)
    , d_number_moments(Moments<D>::number_moments(legendre_order))
{
  //
}

//---------------------------------------------------------------------------//

// Const access via operator() and cardinal cell and moment indices
template<class Equations, class D>
inline const typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::operator()(int cell, int u, int moment) const
{
  Require(moment >= 0);
  Require(moment < d_number_moments);
  Require(u >= 0);
  Require(u <  Equations::number_unknowns());

  int index = moment +
              d_number_moments *
              (cell * Equations::number_unknowns() + u);

  // We got an index; now make sure it's valid
  Ensure(valid_index(index));
  return d_values[index];
}

// Mutable access via operator() and cardinal cell and moment indices
template<class Equations, class D>
inline typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::operator()(int cell, int u, int moment)
{
  //     Cast away const on operator()'s return type
  return const_cast<typename Moments_Field<Equations, D>::value_type&>
  (
      // Add const to *this's type and call const version of operator()
      static_cast<const Moments_Field<Equations, D>&>(*this)(cell, u, moment)
  );
}

//---------------------------------------------------------------------------//

// Const access via operator() and cardinal cell index with l and m
template<class Equations, class D>
inline const typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::
operator()(int cell, int u, int l, int m) const
{
  Require(u >= 0);
  Require(u < Equations::number_unknowns());
  Require(Moments<D>::valid(l, m, d_legendre_order));

  int index = Moments<D>::index(l, m) +
              d_number_moments * (cell * Equations::number_unknowns() + u);

  // We got an index; now make sure it's valid
  Ensure(valid_index(index));
  return d_values[index];
}

// Mutable access via operator() and cardinal cell index with l and m
template<class Equations, class D>
inline typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::
operator()(int cell, int u, int l, int m)
{
  //     Cast away const on operator()'s return type
  return const_cast<typename Moments_Field<Equations, D>::value_type&>
  (
      // Add const to *this's type and call const version of operator()
      static_cast<const Moments_Field<Equations, D>&>(*this)(cell, u, l, m)
  );
}

//---------------------------------------------------------------------------//

// Const access via moments() and 3-d ijk indices.
template<class Equations, class D>
inline const typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::
moment(int i, int j, int k, int u, int l, int m) const
{
  int cell = d_mesh->convert(i, j, k);
  return (*this)(cell, u, l, m);
}

// Mutable access via moments() and 3-d ijk indices.
template<class Equations, class D>
inline typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::
moment(int i, int j, int k, int u, int l, int m)
{
  //     Cast away const on operator()'s return type
  return const_cast<typename Moments_Field<Equations, D>::value_type&>
  (
    // Add const to *this's type and call const version of operator()
    static_cast<const Moments_Field<Equations, D>&>
      (*this).moment(i, j, k, u, l, m)
  );
}

//---------------------------------------------------------------------------//

// Const access via moments() and 2-d ij indices.
template<class Equations, class D>
inline const typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::moment(int i, int j, int u, int l, int m) const
{
  return moment(i, j, 0, u, l, m);
}

// Mutable access via moments() and 2-d ij indices.
template<class Equations, class D>
inline typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::moment(int i, int j, int u, int l, int m)
{
  //     Cast away const on operator()'s return type
  return const_cast<typename Moments_Field<Equations, D>::value_type&>
  (
    // Add const to *this's type and call const version of operator()
    static_cast<const Moments_Field<Equations, D>&>
      (*this).moment(i, j, u, l, m)
  );
}


//---------------------------------------------------------------------------//

// Const access via moments() and 1-d i index.
template<class Equations, class D>
inline const typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::moment(int i, int u, int l) const
{
  return moment(i, 0, 0, u, l, 0);
}

// Mutable access via moments() and 1-d i index.
template<class Equations, class D>
inline typename Moments_Field<Equations, D>::value_type&
Moments_Field<Equations, D>::
moment(int i, int u, int l)
{
  //     Cast away const on operator()'s return type
  return const_cast<typename Moments_Field<Equations, D>::value_type&>
  (
    // Add const to *this's type and call const version of operator()
    static_cast<const Moments_Field<Equations, D>&>
      (*this).moment(i, u, l)
  );
}

}

#endif /* MOMENTS_FIELD_I_HH_ */

//---------------------------------------------------------------------------//
//              end of Moments_Field.i.hh
//---------------------------------------------------------------------------//
